# Copyright 1999-2012 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $

#
# Original Author: Serge V. Zarviroff <zarviroff@gmail.com>
# Purpose: make it easy to create and emerge ebuilds for games' additives (such as mods, scripts, etc.;
# primarily designed for x3 - Reunion, but should work with any target app as it is very universal).
#
# Bugs, patches to zarviroff@gmail.com
#

#
# 	Description:
#
# There are some really good and high-moddable games ported to Linux such as x2, x3 or nwn. And there are plenty
# of various fan-made additives for them. Installing them in Windows is not a very big deal (esp., for x3, as there
# is a special piece of software for that purpose does exist) as Windows' fs are not case-sensetive and most of users
# run the system with administrative rights. In Linux we do have some problems:
# 1. Most of those additives are developed for Windows -> files and directories names contain various register chars oftenly.
# 2. Directory hierarchy of the addon is not standartizied -> actual files/folders can be anywhere in the addon distribution.
# To solve the first problem the source gets "synced" with the game (the source shouldn't be just moved to lowercase as the game
# can contain files or dirs with various register chars in their names, and the source can contain subfolderes which definetely
# belong to the addon and shouldn't be changed). Through the syncronization of the source with the game an array of collisions is
# created (an addon for a game does contain modified files oftenly).
# Solving those problems we face even more: if the package wants to install a file and there is a file with the same name
# in the destination, then it is a collision. But what kind of collision is that? A package could install a file that clones
# an original file; in this case, this file should be removed from the WORKDIR prior to install phase to evade a collision.
# If it differs form the original file, then the original file should be backuped. But what if a file package wants to overwrite
# belongs not to the game but to some other additive that was installed by the user previously? If it clones installed file
# then it's most likely just depends on that additive. But what if it differs from the installed one? In this case we can't
# allow a package to be installed but we have to inform the user why. We should get if this file differs from the backuped
# (original) one or not. If it differs not (i.e., a package wants to install an original file) then the situation is
# resolvable due to the probability that the developer of an addon included that file accidently. Otherwise, the situation
# is not resolvable at all, as that file differs from both original and installed (by some other package) files and
# overwriting it with almost 100% probability will break a package that owns the file making the game behaviour unpredictable.
# Moreover, MODs for the X series games contain data in cat-dat filepairs which numeration order is strict. So, MODs installations
# should be tracked (i.e., uninstalling a MOD that is not the last MOD installed could make the game behaviour unpredictable).
# If this is not the hell, then what is it? :D
#
#
# 	Usage:
#
# An ebuild inheriting this eclass, must contain the name of a game in its name as "prefix-" 
# 	Examples:
# 	games-strategy/x3-turbomod2
# 	games-strategy/x3-battle_scripts

#
#	What it does:
#
# Everything that collisions.eclass does + renames cat-dat-filepairs properly (for x2, x3, etc. games).
#


inherit games collisions break-on-block tracker

EXPORT_FUNCTIONS pkg_setup src_prepare src_install pkg_postinst pkg_postrm

RESTRICT="primaryuri"

# All ebuilds inheriting this eclass must contain the name of a target game as "prefix-".
# Example: games-strategy/x3-turbomod2-${PV}.ebuild for games-simulation/x3
#			games-rpg/nwn-hatd-${PV}.ebuild for games-rpg/nwn
txg_TARGET_NAME="${PN%%-*}"
txg_TARGET_PREFIX="${GAMES_PREFIX_OPT}"

# txg_last_target_datapair_num() {
# 	echo $(ls "${clns_TARGET_ROOT}" -ARr | grep ^[[:digit:]]*\.cat$ | head -n1 | sed 's/\.cat$//')
# }

# txg_last_this_datapair_num() {
# 	echo $(ls "${clns_SOURCESROOT}" -ARr | grep ^[[:digit:]]*\.cat$ | head -n1 | sed 's/\.cat$//')
# }

# 
# Get the number of the datapairs
# $1 = path (usually clns_SOURCESROOT or clns_TARGET_ROOT)
# $2 = 'head' for the first datapair and 'tail' for the last one
#
txg_get_datapair_num()
{
	echo $(ls ${1} -AR | grep ^[[:digit:]]*\.cat$ | sed 's/\.cat$//' | sort | ${2} -n1)
}

#
# This assures the datapairs should be actually renamed. As there could be a situation (esp. when installing the first mod)
# when the mod bears datapairs numerated the right way.
#
# TODO what if it is > ?
#
# txg_datapairs_rename_needed() {
# 	local TARGET_LAST_DATAPAIR_NUM=$(txg_get_datapair_num ${clns_TARGET_ROOT} tail)
# 	local THIS_PKG_FIRST_DATAPAIR_NUM=$(txg_get_datapair_num ${clns_SOURCESROOT} head)
# 	if [[ "${THIS_PKG_FIRST_DATAPAIR_NUM}" =~ ^[0-9]+$ ]]
# 	then
# 		if (( 10#${THIS_PKG_FIRST_DATAPAIR_NUM} <= 10#${TARGET_LAST_DATAPAIR_NUM} ))
# 		then
# 			return 0
# 		else
# 			return 1
# 		fi
# 	else
# 		return 0
# 	fi
# }

#
# txg_rename_catdats() function:
#
# X games' data is stored in pairs of .cat/.dat files (i.e., 05.cat 05.dat). cat/dat pair with a higher number
# has higher "priority" and it' contents "overwriting" contents of a pair with lower number.
# Mods (and even some scripts) are distributed in such data-pairs too. To make a mod work it's pair should
# be properly numbered.
# This function get the last pair' number installed and renames data-pair of the mod properly.
# It's done in a reversed order because there are mods containing several data-pairs.
#
txg_rename_catdats() {
	local IFS=$'\n'

	local last_target_datapair

	tracker_exists "${clns_R_COLLISIONSROOT}" && lastinstalledatom=$(tracker_LastStrictAtom "${clns_R_COLLISIONSROOT}")
	if tracker_isReinstall
	then
		local pair
		local txg_DATAPAIRS
		for pair in $(sed '/[0-9]\.cat[ \t$]/!d;s|^.*/||;s|\.cat.*$||' ${pDB}/${CATEGORY}/${PN}-*/CONTENTS | sort -r)
		do
			txg_DATAPAIRS[${#txg_DATAPAIRS[@]}]="${pair}"
		done
		if (( "${txg_catsInPackage}" == "${#txg_DATAPAIRS[@]}" )) || [[ "${lastinstalledatom}" =~ ${CATEGORY}/${PN} ]]
		then
			last_target_datapair=$((10#${txg_DATAPAIRS[$((${#txg_DATAPAIRS[@]}-1))]}-1))
		else
			eerror "This package can't be reinstalled as it contains another number"
			eerror "of cat-dat-filepairs and/or is not the last package installed."
			eerror ""
			tracker_printErrorsUntil "${clns_R_COLLISIONSROOT}" "${CATEGORY}" "${PN}" 1
			eerror ""
			eerror "Uninstall every listed package first to reinstall this package."
			eerror ""
			die "package can't be reinstalled right now due to strict X cat-dat-filepairs numbering."
		fi
	else
		# the last cat-dat-pair number
		last_target_datapair=$(txg_get_datapair_num ${clns_TARGET_ROOT} tail)
	fi

	local first_source_datapair=$(txg_get_datapair_num ${clns_SOURCESROOT} head)
	local rename_type=-1
	if [[ "${first_source_datapair}" =~ ^[0-9]+$ ]]
	then
		if (( 10#${first_source_datapair} <= 10#${last_target_datapair} ))
		then
			rename_type=0
		elif (( 10#${first_source_datapair} > (( 1 + 10#${last_target_datapair} )) ))
		then
			rename_type=1
		fi
	else
		rename_type=0
	fi
	
	local i
	if (( ${rename_type} == -1 ))
	then
		return
	elif (( ${rename_type} == 0 ))
	then
		for i in $(ls -Ar | grep -i ^.*\.cat$)
		do
			# last_target_datapair could have a 0 (zero) as a first digit. In that case bash will interpret it as an octal
			# So explicitly pointing it is a decimal is a good idea and safe etc.
			mv "${i}" $(printf "%02d" "$((10#${last_target_datapair} + ${txg_catsInPackage}))").cat || die "Failed to rename a .cat file"
			mv "$(ls | grep -i ^${i%.*}.dat$)" $(printf "%02d" "$((10#${last_target_datapair} + ${txg_catsInPackage}))").dat || die "Failed to rename a .dat file"
			(( --txg_catsInPackage ))
		done
	elif (( ${rename_type} == 1 ))
	then
		for i in $(ls -A | grep -i ^.*\.cat$)
		do
			last_target_datapair=$((10#${last_target_datapair} + 1))
			mv "${i}" $(printf "%02d" "${last_target_datapair}").cat || die "Failed to rename a .cat file"
			mv "$(ls | grep -i ^${i%.*}.dat$)" $(printf "%02d" "${last_target_datapair}").dat || die "Failed to rename a .dat file"
		done
	fi
}

thexgames_pkg_setup() {
	[[ -z "${clns_ENV_IS_SET}" ]] && clns_set_ENV "${txg_TARGET_PREFIX}" "${txg_TARGET_NAME}"
	tracker_markreinstall
	bob_bob "/var/db/pkg" "${clns_R_COLLISIONSROOT}"
	return
}

thexgames_src_prepare() {
	cd "${clns_SOURCESROOT}"
	# For X games: detect if it is a package that has cat-dat-filepairs in its SOURCESROOT. If it has - it's a mod that must
	# be tracked via tracker_TRACKFILE and datapairs should be renamed properly. This should be done prior to
	# collisions_src_prepare as datapairs are not collisions themselves and they shouldn't be tricked that way.
	# Rename datafiles for X games
	[[ "${txg_TARGET_NAME}" =~ ^(x2|x3(tc|ap)*)$ ]] && {
		txg_catsInPackage=$(ls -A | grep -i .*\.cat$ | wc -l)
		if (( "${txg_catsInPackage}" > 0 ))
		then
			tracker_STRICTORDER=1
# 			if txg_datapairs_rename_needed
# 			then
				txg_rename_catdats "${txg_catsInPackage}"
# 			fi
		fi
	}

	collisions_src_prepare "${tracker_STRICTORDER}"
}

thexgames_src_install() {
	collisions_src_install

	prepgamesdirs
}

thexgames_pkg_postinst() {
	tracker_print "${clns_R_COLLISIONSROOT}"
	games_pkg_postinst
}

thexgames_pkg_postrm() {
	collisions_pkg_postrm
	tracker_print "${clns_R_COLLISIONSROOT}"
}
